package com.jwgf.canstate;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.jwgf.can.CanMessage;
import com.jwgf.comlibrary.CANManager;
import com.jwgf.common.AppContext;
import com.jwgf.protocolstack.IdComparator;
import com.jwgf.protocolstack.ProtocolStack;
import com.jwgf.protocolstack.ProtocolStackState;
import com.jwgf.smarowindingmachine_unity.logic.MachineParameterSharedPreference;
import com.jwgf.smarowindingmachine_unity.ui.WaitProgressDialog;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;

public class SmaroCanHandState implements ProtocolStackState {

    private int failedCnt = 0;
    private ProtocolStack stack;
    private HashSet<Integer> filterSet = new HashSet<>(50);

    private long timediff = 0;

    public SmaroCanHandState(ProtocolStack stack) {
        this.stack = stack;
        filterSet.add(0xE0);
        filterSet.add(0x10);
        filterSet.add(0x15);
        filterSet.add(0x16);
        filterSet.add(0x20);
        filterSet.add(0x21);
        filterSet.add(0x22);
        filterSet.add(0x23);
        filterSet.add(0x24);
        filterSet.add(0x25);
        filterSet.add(0x26);
        filterSet.add(0x27);
        filterSet.add(0x28);
        filterSet.add(0x29);
        filterSet.add(0x2A);
        filterSet.add(0x2C);
        filterSet.add(0x2D);
        filterSet.add(0x30);
        filterSet.add(0x31);
        filterSet.add(0x32);
        filterSet.add(0x33);
        filterSet.add(0x39);
        filterSet.add(0x75);
        EventBus.getDefault().register(this);
    }

    private Runnable canStateCheck = new Runnable() {

        @Override
        public void run() {

            if (stack.isComStateOK()) {
                stack.setComState(false);
            }
            setFailedCnt(getFailedCnt() + 1);
            if (getFailedCnt() == 2) {
                setFailedCnt(0);
                byte[] request = stack.getCmdExecuting();

                if (request[2] == 0x40 && request[3] == 0x01) {
                    stack.notifyReadFailedListeners();
                } else {
                    stack.notifyWriteFailedListeners();
                }

                stack.setComparator(new IdComparator());
                byte[] cmd = stack.getCmdExecuting();
                if (!Arrays.equals(cmd, MachineParameterSharedPreference.getInstance().getBroadcast().get(0))
                        && !Arrays.equals(cmd, MachineParameterSharedPreference.getInstance().releaseBroadcast().get(0))) {
                    stack.clearCmdbyComparator(cmd);
                }
                stack.setComState(true);
            }
//            Log.e("HandShakeTimeout", "回复超时：" + getFailedCnt() + " " + Arrays.toString(stack.getCmdExecuting()));

            stack.send();
        }
    };

    @Override
    public void handleSend(ProtocolStack stack) {
        if (stack.takeCmd() != null) {
            byte[] data = stack.getCmdExecuting();
            int canId = (data[0] << 8) | (data[1] & 0xff);
            byte[] sendData = new byte[data.length - 2];
            System.arraycopy(data, 2, sendData, 0, sendData.length);
            CANManager.getInstance().write1(canId, sendData);
            timediff = Calendar.getInstance().getTimeInMillis();
//            Log.e("HandShakeTimeout", "发送数据" + Arrays.toString(data));
            // for test
            if(AppContext.isDebug) {
                EventBus.getDefault().post(data);

            }

            stack.getStackHandler().removeCallbacks(canStateCheck);
            stack.getStackHandler().postDelayed(canStateCheck, 2000);

        } else {
            new Handler(Looper.getMainLooper()).post(new Runnable() {

                @Override
                public void run() {
                    WaitProgressDialog.hide();
                }
            });
        }

    }

    @Override
    public void handleRecv(ProtocolStack stack, byte[] recv) {
        int id = ((recv[0] & 0xff) << 8) | (recv[1] & 0xff);
        if (recv.length == 10) {
            byte[] request = stack.getCmdExecuting();
            if (request != null) {
                // normal parameter setting data
                if ((request[1] == recv[3] && request[2] == recv[4] && request[3] == recv[5])) {
                    stack.getStackHandler().removeCallbacks(canStateCheck);
//                    Log.e("HandShakeTimeout", "设置：" + Arrays.toString(request) + " " + Arrays.toString(recv));
                    stack.setComState(true);
                    setFailedCnt(0);
                    stack.notifyWriteSucceedListeners();
                    stack.send();
                    timediff = Calendar.getInstance().getTimeInMillis() - timediff;
                    if (timediff > 500) {
                        Log.e("cantime", timediff + "");
                    }
                } else if (request[1] == recv[3] && request[2] == 0x40 && request[3] == 0x01
                        && request[4] == recv[2]) {
//                    Log.e("HandShakeTimeout", "查询数据：" + Arrays.toString(request) + " " + Arrays.toString(recv));
                    stack.getStackHandler().removeCallbacks(canStateCheck);
                    stack.setComState(true);
                    setFailedCnt(0);
                    stack.notifyReadSucceedListeners(recv);
                    stack.send();
                    timediff = Calendar.getInstance().getTimeInMillis() - timediff;
                    if (timediff > 500) {
                        Log.e("cantime", timediff + "");
                    }
                }
                // broadcast
                else if (request[1] == 0x55 && request[2] == recv[4] && request[3] == recv[5]) {
                    stack.getStackHandler().removeCallbacks(canStateCheck);
                    stack.setComState(true);
                    setFailedCnt(0);
                    stack.send();
//                    Log.e("HandShakeTimeout", "广播数据：" + Arrays.toString(request) + " " + Arrays.toString(recv));
                } else {
//                    Log.e("HandShakeTimeout", "非握手数据：" + Arrays.toString(request) + " " + Arrays.toString(recv));
                }
            } else {
//                Log.e("HandShakeTimeout", Arrays.toString(recv));
            }

        }

    }

    @Subscribe
    public void receive(CanMessage msg) {
        byte[] data = msg.getData();
        int canId = data[1] & 0xff;
        int canfilter = data[2] & 0xff;
        if (canId != 1) {
            return;
        }
        if (filterSet.contains(canfilter)) {
            stack.process(data);
            EventBus.getDefault().cancelEventDelivery(msg);
        }
    }

    public int getFailedCnt() {
        return failedCnt;
    }

    public void setFailedCnt(int failedCnt) {
        this.failedCnt = failedCnt;
    }

}
